using OpenIddict.Abstractions;
using static OpenIddict.Abstractions.OpenIddictConstants;

namespace Identity.HttpAPI.Host.Extensions
{
    public static class ApplicationSeeder
    {
        public static async Task SeedPublicClientAsync(IServiceProvider services)
        {
            using var scope = services.CreateScope();
            var manager = scope.ServiceProvider.GetRequiredService<IOpenIddictApplicationManager>();

            const string clientId = "swagger-client";
            var swaggerRedirectUri = new Uri("https://localhost:7291/swagger/oauth2-redirect.html");
            var vueRedirectUri = new Uri("http://localhost:5173/auth-callback");
            var existing = await manager.FindByClientIdAsync(clientId);

            var requiredPermissions = new[]
            {
        OpenIddictConstants.Permissions.Endpoints.Authorization,
        OpenIddictConstants.Permissions.Endpoints.Token,
        OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
        OpenIddictConstants.Permissions.GrantTypes.RefreshToken,
        OpenIddictConstants.Permissions.ResponseTypes.Code,
        Scopes.OpenId,
        OpenIddictConstants.Permissions.Scopes.Profile,
        OpenIddictConstants.Permissions.Scopes.Email,
        Scopes.OfflineAccess,

        OpenIddictConstants.Permissions.Prefixes.Scope + "api" // 正确的自定义 scope 权限
    };

            if (existing == null)
            {
                var descriptor = new OpenIddictApplicationDescriptor
                {
                    ClientId = clientId,
                    DisplayName = "Swagger UI (public OIDC client)",
                    ClientType = OpenIddictConstants.ClientTypes.Public,
                };

                descriptor.RedirectUris.Add(swaggerRedirectUri);
                descriptor.RedirectUris.Add(vueRedirectUri);

                foreach (var permission in requiredPermissions)
                    descriptor.Permissions.Add(permission);

                descriptor.Requirements.Add(OpenIddictConstants.Requirements.Features.ProofKeyForCodeExchange);

                await manager.CreateAsync(descriptor);
            }
            else
            {
                var existingRedirectUris = await manager.GetRedirectUrisAsync(existing);
                var existingPermissions = await manager.GetPermissionsAsync(existing);
                var existingRequirements = await manager.GetRequirementsAsync(existing);

                var descriptor = new OpenIddictApplicationDescriptor
                {
                    ClientId = clientId,
                    DisplayName = "Swagger UI (public OIDC client)",
                    ClientType = OpenIddictConstants.ClientTypes.Public
                };

                // 合并 redirect URIs
                var redirectSet = new HashSet<string>(existingRedirectUris, StringComparer.OrdinalIgnoreCase);
                foreach (var uri in existingRedirectUris)
                    descriptor.RedirectUris.Add(new Uri(uri));

                if (!redirectSet.Contains(swaggerRedirectUri.ToString()))
                    descriptor.RedirectUris.Add(swaggerRedirectUri);
                if (!redirectSet.Contains(vueRedirectUri.ToString()))
                    descriptor.RedirectUris.Add(vueRedirectUri);

                // 合并 permissions：已有 + 必需
                IEnumerable<string> mergedPermissions;
                if (existingPermissions.IsDefaultOrEmpty)
                    mergedPermissions = requiredPermissions;
                else
                    mergedPermissions = existingPermissions.Union(requiredPermissions);

                foreach (var permission in mergedPermissions.Distinct())
                    descriptor.Permissions.Add(permission);

                // 保留 requirements（例如 PKCE）
                if (!existingRequirements.IsDefaultOrEmpty)
                {
                    foreach (var requirement in existingRequirements)
                        descriptor.Requirements.Add(requirement);
                }

                await manager.UpdateAsync(existing, descriptor);
            }
        }
    }
}